﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Configuration;

namespace GOFconsole
{
    class Chapter15_AssemblyandFactory
    {
        public void AssemblyAndFactoryTest()
        {
            User user = new User();
            IUser iu = DataAccess.CreateUser();//直接得到实际的数据库访问实例，而不存在任何依赖项
            iu.Insert(user);
            iu.GetUser(1);
            //用反射技术获取数据库连接类实例，可以通过配置文件修改不需要重新编译
            IUser iu2 = DatabaseAccessByReflection.CreateUser();
            iu2.Insert(user);
            iu2.GetUser(2);
        }
    }

    class User
    {
        private int Id{get;set;}
        private string Name{get;set;}
    }
    interface IUser
    {
        void Insert(User user);
        User GetUser(int id);
    }
    class SqlServerUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("SqlServer中给User表插数据");
        }
        public User GetUser(int id)
        {
            Console.WriteLine("SqlServer中根据ID获取User表的数据");
            return null;
        }
    }
    class AccessUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("Access中给User表插数据");
        }
        public User GetUser(int id)
        {
            Console.WriteLine("Access中根据ID获取User表的数据");
            return null;
        }
    }

    class DataAccess
    {
        //private static readonly string db = "SqlServer";
        private static readonly string db = "Access";

        public static IUser CreateUser()
        {
            IUser result = null;
            switch (db) //用简单工厂+抽象工厂结合后，剩余的问题就是每增加一个新的数据库方法就要修改SWITCH分支
            { 
                case "SqlServer":
                    result = new SqlServerUser();
                    break;
                case "Access":
                    result = new AccessUser();
                    break;
            }
            return result;
        }
    }

    //用反射来克服工厂模式的不足
    //结合配置文件来达到不重新编译即可切换数据库的功效
    class DatabaseAccessByReflection
    {
        private static readonly string AssemblyName = "GOFconsole"; //程序集名称
        private static readonly string db = ConfigurationSettings.AppSettings["ConnString"];

        public static IUser CreateUser()
        {
            string className = AssemblyName +"." + db + "User"; //拼一个SqlUser类的名字
            return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);    //通过反射获取这个类的实例
        }
    }


}
